#include "mario.h"
#define MARIO_SPEED 0.14f
#define MARIO_V_Y 0.5f;
#define ACC 0.0005f; // Acceleration

extern 	QuadTree *cTree;

CMario::CMario() : CMovable()
{
	isFalling = 0;
	MarioBitmap = NULL;
	pos_x = 100;
	pos_y = 100;
	lowest = GROUND;
	highest = lowest - 60;
	v_x = 0;
	v_y = 0;
	lv = 0;
	came = 0;
	width = 16;
	height = 16;
	anim = 0;
	state = 0;
	isRunning = 0;
	movingWay = 1;
	immuTime = GetTickCount();
	immu = 0;
	CoinGot = 0;
	isShootingTime = GetTickCount();
	bul = new CBullet();
	bul2 = new CBullet();
	mushroom = new CMushroom();
	star = new CStar();
	jumpingCoin = new CJumpingCoin();
	havingStarTime = GetTickCount();
	havingStar = 0;
	blend = 0;
	inHouse = 0;
	pa1 = new CPieceBrick();
	pa2 = new CPieceBrick();
	pa3 = new CPieceBrick();
	pa4 = new CPieceBrick();
	pb1 = new CPieceBrick();
	pb2 = new CPieceBrick();
	pb3 = new CPieceBrick();
	pb4 = new CPieceBrick();
	lifeLeft = 3;
}

CMario::~CMario()
{
	
}

void CMario::Slip()
{
	if(state != 2)
	{
		state = 4;
		anim = 4+lv/2;
	}
}

void CMario::Move(int way,int t)
{
	if(state == 10)
		return;
	float acc = ACC;
	if(state!=1 && state != 2 && state != 4)
	{
		state = 1;
	}
	movingWay = way;
	if(way == 1)
	{
		if(v_x < 0) 
		{
			//Stop(t);
			Slip();
		}
		else if(state == 4)
			state = 1;
		if(v_x < ((1.5+isRunning)*MARIO_SPEED))
			v_x += t*acc;
		else
			Stop(t);
	}
	else
	{
		if(v_x > 0) 
		{
			//Stop(t);
			Slip();
		}
		else if (state == 4)
			state = 1;
		if(-v_x <((1.5+isRunning)*MARIO_SPEED))
			v_x -= t*acc;
		else
			Stop(t);
	}
}

void CMario::Stop(int t)
{
	if(state == 10)
		return;
	float acc = ACC;
	if(v_x > 0) 
	{
		if (v_x > t * acc)
			v_x -= t * acc;
		else 
		{
			if(state != 2)
			{
				state = 0;
				anim = 0;
			}
			v_x = 0;
		}
	}
	if (v_x < 0) 
	{
		if (v_x + t * acc < 0)
			v_x += t * acc;
		else 
		{
			if(state != 2) 
			{
				state = 0;
				anim = 0;
			}
			v_x = 0;
		}
	}
	if(lv == 2 && anim == 4 && GetTickCount()-isShootingTime > 200)
	{
		if(state != 2) 
		{
			state = 0;
			anim = 0;
		}
		else
			anim = 6;
	}
	if(v_x == 0 && state < 2 && (lv < 2 || anim != 4))
	{
		state = 0;
		anim = 0;
	}
}

void CMario::CheckItem()
{
	myRect * rec1 = new myRect;
	myRect * rec2 = new myRect;
	rec1->x = pos_x;
	rec1->y = pos_y;
	rec1->w = width;
	rec1->h = height;
	if(mushroom->life > 0)
	{
		rec2->x = mushroom->pos_x;
		rec2->y = mushroom->pos_y;
		rec2->w = mushroom->width;
		rec2->h = mushroom->height;
		if(cTree->CutX(rec1,rec2) || cTree->CutX(rec2,rec1))
			mushroom->Touch(this);
	}
	if(star->life > 0)
	{
		rec2->x = star->pos_x;
		rec2->y = star->pos_y;
		rec2->w = star->width;
		rec2->h = star->height;
		if(cTree->CutX(rec1,rec2) || cTree->CutX(rec2,rec1))
		{
			star->Touch(this);
			havingStarTime = GetTickCount();
			blend = 2;
		}
	}
	delete rec1;
	delete rec2;
}

void CMario::Finish()
{
	pos_x = 3112;
	v_x = 0;
	v_y = 0.2f;
	came = 1;
	mushroom->life = 0;
	star->life = 0;
}

void CMario::Update(int t)
{
	pos_x += v_x*t;
	pos_y += v_y*t;
	
	if(came == 0 && pos_x >= 3112) 	Finish();
	if(came == 1 && pos_x >= 3112) 	ArrayObj[0]->Die();
	if(pos_x >= 3232) ComeIn();
	if(inHouse == 0 && came == 1 && v_y == 0 && v_x == 0)
	{
		v_x = 0.2f;
		state = 1;
	}
	if(pos_y > 256 && state != 10) Die();
	if(pos_y < highest)
		isFalling = 1;
	if(state == 10 && pos_y >= 400)
	{
		if(lifeLeft > 0)
			NextLife();
		else
		{
			SpriteHandlerOP->Begin(D3DXSPRITE_ALPHABLEND);
			overPic->Render(_BackBuffer);
			SpriteHandlerOP->End();
		}
	}
	if(state == 10)
	{
		v_y += 0.1f;
		return;
	}
	if(immu == 1 && GetTickCount()-immuTime > 200)
	{
		blend = 1-blend;
		if (GetTickCount()-immuTime > 3000) 
		{
			immu = 0;
			blend = 0;
		}
	}
	if(havingStar == 1 && GetTickCount()-havingStarTime > 200)
	{
		blend = 2-blend;
		if(GetTickCount()-havingStarTime > 8000) 
		{
			blend = 0;
			havingStar = 0;
		}
	}

	cTree->Check(pos_x+5,pos_y+2,width-10,1);
	if(cTree->lastRes == 0 && v_y < 0.5f)
		v_y += 0.1f;
	else if(cTree->lastRes > 0)
	{
		if(ArrayObj[cTree->res[0]]->reality < 3)
		{
			v_y = 0;
			isFalling = 0;
			if(state == 2)
			{
				state = 0;
				anim = 0;
			}
			pos_y = ArrayObj[cTree->res[0]]->pos_y - ArrayObj[cTree->res[0]]->height;
			lowest = pos_y;
		}
	}

	cTree->Check(pos_x+2,pos_y+2,width-4,1);
	if(cTree->lastRes > 0)
	{
		if(ArrayObj[cTree->res[0]]->reality >= 20)
		{
			if(v_y > 0) ArrayObj[cTree->res[0]]->isJumpedOn(this);
			v_y = -0.3f;
		}
		else 
			ArrayObj[cTree->res[0]]->Touch(this);
	}
	if(v_y > 0) 	isFalling = 1;
	//top
	cTree->Check(pos_x+7,pos_y-height+2,width-14,1);
	if(cTree->lastRes > 0)
	{
		if(ArrayObj[cTree->res[0]]->reality < 3)
		{
			pos_y = ArrayObj[cTree->res[0]]->pos_y + height;
			v_y = 0.2f;
			isFalling = 1;
			ArrayObj[cTree->res[0]]->Hitted(this);
		}
		for(int i = 0;i < cTree->lastRes; i++)
			if(ArrayObj[cTree->res[i]]->reality > 3)
				ArrayObj[cTree->res[i]]->Touch(this);
	}
	// right
	cTree->Check(pos_x+width-1,pos_y-height+5,1,height-10);
	if(cTree->lastRes > 0)
	{
		if(ArrayObj[cTree->res[0]]->reality < 3)
		{
			pos_x = ArrayObj[cTree->res[0]]->pos_x - width;
			v_x = 0;
		}
		for(int i = 0;i < cTree->lastRes; i++)
			if(ArrayObj[cTree->res[i]]->reality > 3)
				if(pos_x+width - 3 >= ArrayObj[cTree->res[i]]->pos_x)
					ArrayObj[cTree->res[i]]->Touch(this);

	}
	//left
	cTree->Check(pos_x,pos_y-height+5,1,height-10);
	if(cTree->lastRes > 0)
	{
		if(ArrayObj[cTree->res[0]]->reality < 3)
		{
			pos_x = ArrayObj[cTree->res[0]]->pos_x + ArrayObj[cTree->res[0]]->width+1;
			v_x = 0;
		}
		for(int i = 0;i < cTree->lastRes; i++)
			if(ArrayObj[cTree->res[i]]->reality > 3)
				if(pos_x + 3 <= ArrayObj[cTree->res[i]]->pos_x + ArrayObj[cTree->res[i]]->width)
					ArrayObj[cTree->res[i]]->Touch(this);
	}

	CheckItem();
}

void CMario::Jump()
{
	highest = (lowest - 60) - 30 * abs(v_x);
	state = 2;
	anim = 5+lv/2;
	if(isFalling == 0)
		v_y = -0.5f;
}

void CMario::JumpShort()
{
	highest = (lowest - 20) - 20 * abs(v_x);
	if(state != 6)
	{
		state = 2;
		anim = 5+lv/2;
	}
	if(isFalling == 0)
		v_y = -0.5f;
}

void CMario::lvUp()
{
	if(lv < 2)
		lv++;
	if(lv > 0)
	{
		width = 16;
		height = 32;
	}
}

void CMario::Die()
{
	width = 16;
	height = 16;
	anim = 0;
	v_y = -0.8f;
	lv = -1;
	state = 10;
	v_x = 0;
}

void CMario::lvDown()
{
	if(immu == 1) return;
	if(lv > 0)
	{
		lv = 0;
		width = 16;
		height = 16;
		immu = 1;
		blend = 1;
		immuTime = GetTickCount();
	}
	else
		Die();
}

void CMario::SitDown(int t)
{
	if(state!=2)
	{
		state = 6;
		if(lv > 0) height = 27;
	}
	if(lv == 0)
		anim = 0;
	else
		anim = 6+lv/2;
	Stop(t);
}

void CMario::StandUp()
{
	if(state==6)
	{
		state = 0;
		anim = 0;
	}
	if(lv == 0) height = 16;
	else height=32;
}

void CMario::Shoot()
{
	isRunning = 1;	
	if(lv < 2)
		return;
	if(bul->life == 0)
	{
		bul->ActivateBullet(movingWay,pos_x,pos_y);
		anim = 4;
		isShootingTime = GetTickCount();
	}
	else if (bul2->life == 0)
	{
		bul2->ActivateBullet(movingWay,pos_x,pos_y);
		anim = 4;
		isShootingTime = GetTickCount();	
	}
}

void CMario::RenderFrame(LPDIRECT3DDEVICE9 d3ddv, int t)
{
	DWORD now = GetTickCount();
	Update(t);
	//if (pos_x - scr_x >= 16*6)
		 scr_x=pos_x-16*6;
	if(bul->life > 0)	
		bul->RenderFrame(d3ddv,t);
	if(bul2->life > 0)
		bul2->RenderFrame(d3ddv,t);

	float gg = abs(v_x);
	if(abs(v_x) < 0.15f) gg = 0.15f;
	if ((now - last_time) > 10/gg)
	{
		if(state == 1)
			anim=(anim+1) % 3 + 1 ;
		last_time = now;
	}
	_SpriteHandler->Begin(D3DXSPRITE_ALPHABLEND);
	MarioBitmap->Render(_BackBuffer,pos_x,pos_y,width,height,lv,anim,movingWay,blend);
	_SpriteHandler->End();
	SpriteHandlerNP->Begin(D3DXSPRITE_ALPHABLEND);
		NumberPic->Render(_BackBuffer,28,0,lifeLeft);
NumberPic->Render(_BackBuffer,135,0,CoinGot%10);
NumberPic->Render(_BackBuffer,120,0,(CoinGot/10)%10);

		SpriteHandlerNP->End();
}

void CMario::LoadResources(LPDIRECT3DDEVICE9 d3ddv)
{
	D3DXCreateSprite(d3ddv,&_SpriteHandler);
	HRESULT res = D3DXCreateSprite(d3ddv,&_SpriteHandler);
	MarioBitmap = new CSprite(_SpriteHandler,L"Mario.bmp");
}

void CMario::ComeIn()
{
	v_x = 0;
	inHouse = 1;
}

void CMario::NewStart()
{
	pos_x = 100;
	pos_y = 100;
	came = 0;
	inHouse = 0;
}

void CMario::NextLife()
{
	pos_x = 100;
	pos_y = 100;
	state = 0;
	immu = 1;
	immuTime = GetTickCount();
	blend = 1;
	lv = 0;
	v_x = 0;
	v_y = 0;
	lifeLeft--;
}